package com.cskaoyan.javase.oop1._0introduction;

/**
 * @description: 定义类和创建对象
 * @author: wuguidong@cskaoyan.onaliyun.com
 **/

/**
 * 定义学生类
 *     分析学生类中的属性和行为，根据学生类的属性和行为来定义学生类。
 * 创建学生类对象，给属性赋值，并调用成员方法
 *
 *
 * 现在我们已经知道了类是创建对象的模板,而对象是面向对象程序的基本组成单位
 * 1,如何定义一个类?
 *  定义类的语法:
 *  [各种修饰符] class 类名{
 *      //类体
 *  }
 *  [各种修饰符]主要包括访问权限修饰符,final,abstract等等,这里是完全可以省略的
 *  在一个java文件当中只能定义一个public修饰的类,但是可以定义多个非public类
 *  约定:
 *      在日常的开发中,极少见把多个class写在同一个java文件中,多数情况下一个java文件里就只有一个public class 没有别的
 *      但是我们在上课当中,为了上课方便,我们把多个类定义在同一个java文件中
 * 一个java文件下的多个class是什么关系呢? 关系主要有两个:
 *      1,是属于同包关系
 *      2,属于同一个编译单元(挖坑)
 * 类的命名: 它属于一个标识符,遵循"大驼峰"式的命名规范,它的命名最好"见名知意"
 *
 * 类需要提取全体对象的共性特征来作为创建对象的模板,
 *      在类中使用"属性"描述对象的共性外貌特征
 *      使用"行为"描述对象的共性行为特征
 *
 * 属性在类中如何体现呢?
 * 在类中使用"成员变量"表示对象的属性
 * 成员变量: 类比于"局部变量"是处在"局部"位置的变量称之为"局部变量","局部": 主要是方法的内部和方法的形参列表中
 *          那么处在"成员位置"的变量就是成员变量
 *          成员位置: 在类体当中,除开局部位置的其它位置就是成员位置
 * 在多数情况下,定义一个类都建议开门见山的定义成员变量
 * 定义成员变量的语法:
 *      [各种修饰符] 数据类型 变量名;
 *      [各种修饰符]这里是可以省略的,具体的关键字后面再学,目前我们全部省略
 *
 * 行为在类中如何表现呢?
 * 在类中使用"成员方法"来描述对象的行为
 * 成员方法: 处在"成员位置"的方法称之为成员方法,注意我们讲对象的行为的"成员方法"指的是不带static修饰的方法
 *      或者称之为"普通成员方法"
 * 语法:
 *      [各种修饰符] (不能有static) 返回值类型 方法名(形参列表){
 *          //方法体
 *      }
 *
 *  类定义完后,怎么创建对象呢?对象的属性和行为怎么去访问呢?
 *
 * 创建对象的语法:
 *      在访问权限允许的情况下,在方法中使用以下语法:
 *      类名 对象名 = new 类名();
 * 访问对象的成员变量和方法:
 *      使用对象名点访问对象的成员(成员变量+成员方法统称成员)
 *      其中在访问对象的属性时,因为它们是对象的成员变量,所以它们具有默认值 ---> 对象的成员变量应该存储在对象当中,在堆上
 *
 * 思考: 如果没有创建对象,能否直接访问对象的属性和行为呢?
 *   不能,我们认为成员变量和(普通)成员方法属于对象,必须有存在对象才能访问
 *
 *
 *  > 注意事项
 *
 * - **类可以嵌套定义叫做内部类**，但是现在不要这么做，一个Java文件中定义多个class应该并列而不是包含
 * - 一个Java文件中的多个class是同包（文件夹）关系
 * - 一个类当中，应该开门见山的定义成员变量，而后再写成员方法
 * - 类中没有的属性和行为，对象是不可能有的，类是模板，模板中有才能创建出来
 * - 使用new关键字就会创建新的对象，两条new语句创建的对象是完全独立的
 *
 */
//Demo类作为public修饰的类,作为测试Student类的类,在该类中去创建Student类的对象
public class Demo2 {

    //成员位置
    public static void main(String[] args) {
        //test();
        //创建Student对象
        Student s = new Student();
        Student s2 = new Student();
        //直接打印对象名
        //com.cskaoyan.javase.oop1._0introduction.Student@1540e19d
        //全限定类名 + @ + 地址值
        //打印对象名得到地址值是可以被修改掉的(挖坑)
        System.out.println(s);
        System.out.println(s2);


        //访问对象的属性
        System.out.println(s.age); //0
        System.out.println(s.gender); //null
        s.stuId = 10;
        System.out.println(s.stuId); //10


        //访问对象的行为
        s.eat();
        s.sleep();
        s.study();

        Cat cat = new Cat();
    }

    public static void test(){}

    //成员位置
   static class Cat{

    }

}

//class Cat{}

//定义学生类
class Student{

    //属性,定义成员变量
    //姓名,年龄,性别,学号...
    String name;
    int age;
    //性别建议使用String或者char类型的gender,不建议sex
    //在很多时候,程序员喜欢用布尔类型的isMale或者isFemale来定义性别属性,
    //这种方式是可以的,但是有些时候会出现问题,建议不要这么使用(挖坑)
    String gender;
    int stuId;

    //行为: 吃饭,睡觉,学习...
    public void eat(){
        System.out.println("我除了学习就是吃饭!");
    }
    public void sleep(){
        System.out.println("你这个年龄段,你怎么睡得早的?");
    }
    public void study(){
        System.out.println("学习使我快乐!");
    }

    //在成员方法中是可以操作该对象的成员变量的
    public void test(){
        System.out.println(age);
    }


}
